如果結構中每一個欄位都相同,且使用可以比較的型別,那麼該結構型別的變數就可以互相比較。
package main
import "fmt"
type point struct {
x int
y int
}
func main() {
point1 := struct {
x int
y int
}{10, 10}
point2 := struct {
x int
y int
}{10, 10}
point3 := point{10, 10}
fmt.Println("point1 == point2:", point1 == point2)
fmt.Println("point1 == point3:", point1 == point3)
}
Go 語言屬於強行別語言,只有相同的型別才可以做比較,然而結構在這方面比較彈性,如果函式中定義的匿名結構型別和其他結構型別有相同的欄位,Go 允許他們做比較。
package main
import "fmt"
type point struct { //具名函式
x int
y int
}
func main() {
point1 := struct { //匿名函式(有給初始值)
x int
y int
}{10, 10}
point2 := struct { //匿名函式(有給初始值)
x int
y int
}{10, 10}
point3 := struct { //匿名函式(沒給初始值)
x int
y int
}{}
point3.x = 10
point3.y = 20
point4 := point{10, 10}
fmt.Println("point1 == point2:", point1 == point2)
fmt.Println("point1 == point4:", point1 == point4)
fmt.Println("point3 == point4:", point3 == point4)
}
輸出結果:
point1 == point2: true
point1 == point4: true
point3 == point4: false
此練習證明,儘管匿名結構變數只能建立一次,但用起來跟具名結構變數一樣,確實可以互相比較。
雖然說Go不支援繼承,但其設計者提供了一個有趣替代方式 : 在結構中內嵌其他結構。
內嵌和其他結構型別當成欄位是不一樣的;當我們把結構B嵌入結構A時,B的欄位會被提升(promoted),成結構A自身的欄位,就好像是A的結構型別內定義一樣。
要內嵌一個結構,寫法就像平時定義欄位一樣,只是不必指定欄位名,只須加上來源的結構型名稱即可。
格式如:
type <型別名稱> struct {
<欄位> <型別> // 正常欄位定義
<結構型別> // 內嵌結構型別(不寫欄位名稱)
}
我們可以內嵌任何型別,指示內嵌核心型別並非常見做法也沒啥用處,通常會拿來內嵌自訂型別或是結構。
3.1 存取內嵌型別
<結構變數>.<內嵌(結構)型別>
或是存取內嵌結構的欄位
<結構變數>.<內嵌(結構)型別>.<欄位名稱>
<結構變數>.<提升的欄位名稱>
範例1:
package main
import "fmt"
// 定義一個Person結構
type Person struct {
Name string
Age int
}
// 定義一個Student結構,內嵌了Person結構
type Student struct {
Person // 內嵌Person結構,不需要指定欄位名
Grade int
}
func main() {
// 建立一個Student實例
student := Student{
Person: Person{
Name: "Alice",
Age: 20,
},
Grade: 12,
}
// 存取Student的字段和內嵌的Person結構的字段
fmt.Println("Name:", student.Person.Name) // 存取內嵌結構的字段
fmt.Println("Age:", student.Person.Age) // 存取內嵌結構的字段
fmt.Println("Grade:", student.Grade) // 存取Student結構的字段
// 如果內嵌結構的欄位和Student結構有相同的欄位名,可以使用結構類型的名稱來存取
student.Age = 21 // 存取Student結構的Age字段
fmt.Println("Age (Student):", student.Age)
// 提升的欄位名,不需要使用內嵌結構的名稱,可以直接存取
fmt.Println("Name (提升):", student.Name) // 存取提升的字段
}
範例2:
package main
import "fmt"
// 定義一個Person結構
type Person struct {
Name string
Age int
}
// 定義一個Student結構,內嵌了Person結構
type Student struct {
Person // 內嵌Person結構,不需要指定欄位名
Grade int
}
func main() {
// 建立一個Student實例
student := Student{
Person: Person{
Name: "Alice",
Age: 20,
},
Grade: 12,
}
fmt.Println("Name:", student.Name)
fmt.Println("Age:", student.Age)
fmt.Println("Grade:", student.Grade)
}
然而在真實世界中,嵌入的用法不常見,主要是因為會帶來額外複雜度跟問題,Go 開發者通常偏好直接將其他結構當成目標結構的具名欄位。
在Go語言中,字段名的首字母的大小寫有著特定的意義:
如果欄位名稱以大寫字母開頭(例如Age和Name),則該欄位是公開的(exported),可以從套件外部存取。
如果欄位名稱以小寫字母開頭(例如age和name),則該欄位是私有的,只能在套件內部存取。
因此,根據你的需求和設計,你可以選擇將字段名的首字母設為大寫或小寫。
如果你希望Age和Name欄位可以從套件外部訪問,則將它們設為大寫字母開頭是合適的。 如果你希望這些欄位只能在套件內部訪問,則將它們設為小寫字母開頭。
在上面的範例中,我將Age和Name欄位設為大寫字母開頭,因此它們是公開的,可以從套件外部存取。 這樣可以讓你更靈活地控制字段的存取權限。